﻿using MediatR;
using Newtonsoft.Json;
using RBAC_Uthorization.Domain;
using RBAC_Uthorization.Domain.Entity;
using RBAC_Uthorization.Infrstructre.Impl;
using RBAC_Uthorization.Infrstructre.Interface;
using RBAC_Uthorization.Read.API.Application.Command.MenuCommand;
using RBAC_Uthorization.Read.API.DTO;
using RBAC_Uthorization.Read.API.DTO.Response.Menu;
using RBAC_Uthorization.Read.API.Extensions;
using StackExchange.Redis;
using System.Collections.Generic;

namespace RBAC_Uthorization.Read.API.Application.CommandHandlers.MenuHandler
{

    public class MenuTreeRoleIdShowCommandHandlers : IRequestHandler<MenuTreeRoleIdShowCommand, ApiResult<List<MenuTreeRoleIdShowDto>>>
    {
        private readonly IMenuRepository _menuRepository;
        private readonly IRoleMenuRepository _roleMenuRepository;
        private readonly IRoleRepository _roleRepository;
        private readonly IUserRoleRepository userRoleRepository;
        private readonly IConfiguration _configuration;
        private readonly RedisConnectionService _redisConnectionService;

        public MenuTreeRoleIdShowCommandHandlers(IMenuRepository menuRepository, IRoleMenuRepository roleMenuRepository, IUserRoleRepository userRoleRepository, IRoleRepository roleRepository, IConfiguration configuration, RedisConnectionService redisConnectionService)
        {
            _menuRepository = menuRepository;
            _roleMenuRepository = roleMenuRepository;
            this.userRoleRepository = userRoleRepository;
            _roleRepository = roleRepository;
            _configuration = configuration;
            _redisConnectionService = redisConnectionService;
        }

        public async Task<ApiResult<List<MenuTreeRoleIdShowDto>>> Handle(MenuTreeRoleIdShowCommand request, CancellationToken cancellationToken)
        {
            if (_configuration["Redis:Redisif"] == "1")
            {
                //如果redis中有数据
                var cachedMenuIds = await _redisConnectionService.GetAsync($"user:{request.create_user}:{request.sys_id}:menuIds");
                if (cachedMenuIds != null)
                {
                    return new ApiResult<List<MenuTreeRoleIdShowDto>>()
                    {
                        Code = ResultCode.Ok,
                        Message = "菜单显示(缓存)",
                        Data = JsonConvert.DeserializeObject<List<MenuTreeRoleIdShowDto>>(cachedMenuIds)
                    };
                }

                var cachedRoleIds = await _redisConnectionService.GetAsync($"user:{request.create_user}:{request.sys_id}:roleIds");
                if (cachedRoleIds != null)
                {
                    var roleIdss = JsonConvert.DeserializeObject<List<int>>(cachedRoleIds);

                    var roleMenuss = await _roleMenuRepository.GetAllAsunc(rm => roleIdss.Contains(rm.role_id) && rm.del_flag == 0);
                    var menuIdss = roleMenuss.Select(rm => rm.menu_id).Distinct().ToList();
                    var menulists = JsonConvert.DeserializeObject<List<sys_menu>>(await _redisConnectionService.GetAsync($"Menu_{request.sys_id}"));
                    var menuss = menulists.Where(x => menuIdss.Contains(x.id)).ToList();
                    var menuTrees = BuildMenuTree(menuss, 0);

                    // 将菜单ID存储到Redis
                    await _redisConnectionService.SetAsync($"user:{request.create_user}:{request.sys_id}:menuIds", JsonConvert.SerializeObject(menuTrees));
                    return new ApiResult<List<MenuTreeRoleIdShowDto>> { Code = ResultCode.Ok, Message = "菜单显示(缓存)", Data = menuTrees };
                }

                // 从数据库中获取角色对象ID
                var userRoles = await userRoleRepository.GetAllAsunc(ur => ur.user_id == Convert.ToInt32(request.create_user)&&ur.del_flag==0);
                var roleIds = userRoles.Select(ur => ur.role_id).ToList();

                // 查询角色菜单
                var roleMenus = await _roleMenuRepository.GetAllAsunc(rm => roleIds.Contains(rm.role_id) && rm.del_flag == 0);
                var menuIds = roleMenus.Select(rm => rm.menu_id).Distinct().ToList();

                var menulist = JsonConvert.DeserializeObject<List<sys_menu>>(await _redisConnectionService.GetAsync($"Menu_{request.sys_id}"));
                var menus = menulist.Where(x => menuIds.Contains(x.id)).ToList();
                var menuTree = BuildMenuTree(menus, 0);

                // 将菜单ID存储到Redis
                await _redisConnectionService.SetAsync($"user:{request.create_user}:{request.sys_id}:menuIds", JsonConvert.SerializeObject(menuTree));
                await _redisConnectionService.SetAsync($"user:{request.create_user}:{request.sys_id}:roleIds", JsonConvert.SerializeObject(roleIds));

                return new ApiResult<List<MenuTreeRoleIdShowDto>> { Code = ResultCode.Ok, Message = "菜单显示(缓存)", Data = menuTree };
            }
            else
            {
                string[] strings = request.role_id.Split(',');
                List<int> roleIdss = new List<int>();
                foreach (var item in strings)
                {
                    if (!string.IsNullOrEmpty(item))
                    {
                        roleIdss.Add(Convert.ToInt32(item));
                    }
                }

                // 查询角色菜单
                var roleMenus = await _roleMenuRepository.GetAllAsunc(rm => roleIdss.Contains(rm.role_id)&&rm.del_flag==0);
                var menuIds = roleMenus.Select(rm => rm.menu_id).Distinct().ToList();
                var menus = await _menuRepository.GetAllAsunc(x => menuIds.Contains(x.id) && x.del_flag == 0);
                var menuTree = BuildMenuTree(menus, 0);

                return new ApiResult<List<MenuTreeRoleIdShowDto>> { Code = ResultCode.Ok, Message = "菜单显示", Data = menuTree };
            }
        }

        private List<MenuTreeRoleIdShowDto> BuildMenuTree(List<sys_menu> menus, int? parentId)
        {
            var list = new List<MenuTreeRoleIdShowDto>();
            var menuList = menus.Where(x => x.parent_id == parentId&&x.del_flag==0).ToList();
            foreach (var item in menuList)
            {
                var menu = new MenuTreeRoleIdShowDto
                {
                    value = item.id,
                    label = item.menu_name,
                    menu_url = item.menu_url,
                    children = BuildMenuTree(menus, item.id).Count > 0 ? BuildMenuTree(menus, item.id) : null
                };
                list.Add(menu);
            }
            return list;
        }
    }
}
